<template>
  <div class="app-container">
    <div class="filter-container">
      <el-button
        class="filter-item"
        type="primary"
        icon="el-icon-plus"
        @click="handleCreateClicked"
      >
        {{ $t('table.add') }}
      </el-button>
    </div>

    <el-table
      v-loading="listLoading"
      :data="tracksList"
      border
      fit
      highlight-current-row
      style="width: 100%;"
      @sort-change="sortChange"
    >
      <el-table-column
        :label="$t('resTracks.id')"
        prop="id"
        sortable="custom"
        align="center"
        width="80"
        :class-name="getSortClass('id')"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.id }}</span>
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('resTracks.tag')"
        align="center"
      >
        <template slot-scope="{row}">
          <span
            class="link-type"
            @click="handleUpdateClicked(row)"
          >{{ row.tag }}</span>
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('resTracks.play')"
        align="center"
      >
        <template slot-scope="{row}">
          <div>
            <AudioPlayer v-if="row.file" :src="row.file.path | resourceFilter" />
            <span v-else>没有内容</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('resTracks.relatedSong')"
        align="center"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.relatedSong.title }}</span>
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('resTracks.uploader')"
        align="center"
      >
        <template slot-scope="scope">
          <span>{{ scope.row.uploadedByUser.username }}</span>
        </template>
      </el-table-column>

      <el-table-column
        :label="$t('table.actions')"
        align="center"
        width="230"
        class-name="fixed-width"
      >
        <template slot-scope="{row}">
          <el-button
            size="mini"
            type="danger"
            @click="handleDelete(row)"
          >
            {{ $t('res.delete') }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="listQuery.page"
      :limit.sync="listQuery.limit"
      @pagination="getList"
    />

    <el-dialog
      :title="$t('res.' + dialogStatus)"
      :visible.sync="dialogFormVisible"
    >
      <el-form
        ref="dataForm"
        :rules="rules"
        :model="tempTrackData"
        label-position="left"
        label-width="100px"
        style="width: 400px; margin-left:50px;"
      >
        <el-form-item
          :label="$t('resTracks.tag')"
          prop="tag"
        >
          <el-input v-model="tempTrackData.tag" />
        </el-form-item>
        <el-form-item
          :label="$t('resTracks.file')"
          prop="file"
        >
          <el-upload
            ref="upload"
            class="upload-demo"
            name="image"
            action="#"
            accept=".mp3 .aac"
            :limit="1"
            :on-change="handleFileAdded"
            :on-remove="handleRemoveUpload"
            :file-list="tempUploadList"
            :auto-upload="false"
            list-type="text"
          >
            <el-button
              size="small"
              type="primary"
            >
              点击上传
            </el-button>
            <div
              slot="tip"
              class="el-upload__tip"
            >
              只能上传mp3/aac文件
            </div>
          </el-upload>
        </el-form-item>
      </el-form>
      <div
        slot="footer"
        class="dialog-footer"
      >
        <el-button @click="dialogFormVisible = false">
          {{ $t('table.cancel') }}
        </el-button>
        <el-button
          type="primary"
          @click="dialogStatus==='create'?createData():updateData()"
        >
          {{ $t('table.confirm') }}
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { CreateQueryParams, QuerySort } from '@nestjsx/crud-request'
import { Form } from 'element-ui'
import * as _ from 'lodash'
import Pagination from '@/components/Pagination/index.vue'
import AudioPlayer from '@/components/AudioPlayer/index.vue'
import { CrudPaginatedRes, Track, defaultTrackData, getTracks, createTrack, updateTrack, removeTrack, ResourceFile } from '@/api'
import { FileListItem, ElUploadInternalFileDetail } from 'element-ui/types/upload'
import { resourceFilter, elFileListFilter } from '@/filters'
import { UserModule } from '@/store/modules/user'

@Component({
  name: 'TracksIndex',
  components: {
    Pagination,
    AudioPlayer
  }
})
export default class extends Vue {
  private listQuery: CreateQueryParams = {
    join: [
      { field: 'file' },
      { field: 'uploadedByUser', select: ['id', 'username'] },
      { field: 'relatedSong', select: ['id', 'title'] }
    ],
    sort: [{
      field: 'id',
      order: 'ASC'
    }],
    limit: 20,
    page: 1
  }

  private tracksList: Track[] = []
  private total = 0
  private listLoading = true
  private dialogFormVisible = false
  private dialogStatus = ''
  private rules = {
    file: [{ required: true }],
    tag: [{ type: 'string', required: true, message: () => this.$t('resTracks.messages.requireTag'), trigger: 'change' }]
  }

  private tempTrackData = defaultTrackData as Track
  private tempUploadList: FileListItem[] = []

  private get header () {
    return {
      'Content-Type': 'multipart/form-data',
      Authorization: 'Bearer ' + UserModule.token
    }
  }

  private get baseApi () {
    return process.env.VUE_APP_BASE_API
  }

  created () {
    this.getList()
  }

  private async getList () {
    const { data } = await getTracks(this.listQuery)
    this.tracksList = (data as CrudPaginatedRes<Track>).data
    this.total = (data as CrudPaginatedRes<Track>).total
    this.listLoading = false
  }

  private handleFilter () {
    this.listQuery.page = 1
    this.getList()
  }

  private sortChange (data: any) {
    const { prop, order } = data
    const index = _.findIndex<QuerySort>(this.listQuery.sort as QuerySort[], { field: prop })

    if (order !== null) {
      if (index !== -1) {
        (this.listQuery.sort as QuerySort[])[index].order = order === 'ascending' ? 'ASC' : 'DESC'
      } else {
        (this.listQuery.sort as QuerySort[]).push({ field: prop, order: 'ASC' })
      }
    } else {
      if (index !== -1) {
        (this.listQuery.sort as QuerySort[]).splice(index, 1)
      }
    }

    this.handleFilter()
  }

  private getSortClass (key: string) {
    const sort = _.find<QuerySort>(this.listQuery.sort as QuerySort[], { field: key })
    return sort && (sort.order === 'ASC' ? 'ascending' : sort.order === 'DESC' ? 'descending' : null)
  }

  private resetTempData () {
    this.tempTrackData = _.cloneDeep(defaultTrackData) as Track
    this.tempUploadList = []
  }

  private handleFileAdded (file: ElUploadInternalFileDetail) {
    this.tempTrackData.file = file.raw
  }

  private handleRemoveUpload (file: FileListItem, fileList: FileListItem[]) {
    const index = fileList.indexOf(file)
    this.tempUploadList.splice(index, 1)
  }

  private handleCreateClicked () {
    this.resetTempData()
    this.dialogStatus = 'create'
    this.dialogFormVisible = true
    this.$nextTick(() => {
      (this.$refs.dataForm as Form).clearValidate()
    })
  }

  private createData () {
    (this.$refs.dataForm as Form).validate(async valid => {
      if (valid) {
        const { id, ...trackData } = this.tempTrackData
        const { data } = await createTrack(trackData)
        this.tracksList.unshift(data)
        this.dialogFormVisible = false
        this.resetTempData()
        this.$notify({
          title: '成功',
          message: '创建成功',
          type: 'success',
          duration: 2000
        })
      }
    })
  }

  private handleUpdateClicked (row: Track) {
    this.tempTrackData = _.cloneDeep(row)
    if (row.file) {
      this.tempUploadList = elFileListFilter([(row.file as Required<ResourceFile>).path])
    }
    this.dialogStatus = 'update'
    this.dialogFormVisible = true
    this.$nextTick(() => {
      (this.$refs.dataForm as Form).clearValidate()
    })
  }

  private updateData () {
    (this.$refs.dataForm as Form).validate(async valid => {
      if (valid) {
        const { id, ...trackData } = this.tempTrackData
        const { data } = await updateTrack(id, trackData)
        const index = _.findIndex(this.tracksList, { id })
        this.tracksList.splice(index, 1, data)
        this.dialogFormVisible = false
        this.resetTempData()
        this.$notify({
          title: '成功',
          message: '修改成功',
          type: 'success',
          duration: 2000
        })
      }
    })
  }

  private async handleDelete (row: Track) {
    const { data } = await removeTrack(row.id)
    const index = _.findIndex(this.tracksList, { id: row.id })
    this.tracksList.splice(index, 1, data)
    this.$notify({
      title: '成功',
      message: '该资源已被移除',
      type: 'success',
      duration: 2000
    })
  }
}
</script>
